#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

int getHour(time_t now)
{
    struct tm* ltm = localtime(&now);
    return ltm->tm_hour;
}

char* greetAboutTime(int hour)
{
    char* word;
    if (hour > 6 && hour <= 12)
    {
        word = (char*) "Good morning!";
    } else if (hour > 12 && hour <= 18)
    {
        word = (char*) "Good afternoon!";
    } else
    {
        word = (char*) "Good night!";
    }
    return word;
}

char* greetToUser(char* user)
{
    char* buff = (char*) malloc(strlen(user) + 5 * sizeof(char));
    sprintf(buff, "Hi, %s", user);
    return buff;
}

char* sayHello(time_t now, char* user)
{
    int hour = getHour(now);
    char* t = greetAboutTime(hour);
    char* u = greetToUser(user);
    char* greeting = (char*) malloc(strlen(u) + strlen(t) + 3);
    sprintf(greeting, "%s. %s", u, t);
    free(t);
    free(u);
    return greeting;
}

void testSayHello() {
    time_t now = time(0);
    char* user = (char*) "John";

    // Test case 1: greeting in the morning
    struct tm* morning = localtime(&now);
    morning->tm_hour = 7;
    time_t am = mktime(morning);
    char* actual = sayHello(am, user);
    char* expected = (char*) "Hi, John. Good morning!";
    assert(0 == strcmp(actual, expected));
    free(actual);

    // Test case 2: greeting in the afternoon
    struct tm* afternoon = localtime(&now);
    afternoon->tm_hour = 13;
    time_t pm = mktime(afternoon);
    actual = sayHello(pm, user);
    expected = (char*) "Hi, John. Good afternoon!";
    assert(0 == strcmp(actual, expected));
    free(actual);
    
    // Test case 3: greeting at night
    struct tm* night = localtime(&now);
    night->tm_hour = 20;
    time_t nt = mktime(night);
    actual = sayHello(nt, user);
    expected = (char*) "Hi, John. Good night!";
    assert(0 == strcmp(actual, expected));
    free(actual);
}

int main()
{
    testSayHello();

    time_t now = time(0);
    char* user = (char*) "John";
    printf(sayHello(now, user));
    printf("\n");

    struct tm* morning = localtime(&now);
    morning->tm_hour = 7;
    time_t am = mktime(morning);
    printf(sayHello(am, user));
    printf("\n");

    struct tm* afternoon = localtime(&now);
    afternoon->tm_hour = 13;
    time_t pm = mktime(afternoon);
    printf(sayHello(pm, user));
    printf("\n");

    struct tm* night = localtime(&now);
    night->tm_hour = 20;
    time_t nt = mktime(night);
    printf(sayHello(nt, user));
    printf("\n");
    return 0;
}
